<?

class genericClass extends Root{

	var $Module;
	var $Referent;
	var $IdObjClass;
	var $ObjectType;
	var $Historique = Array();
	//Tableaux pour linsertion
	var $Parents = Array();
	var $Enfants = Array();
	var $Error = Array();
	//Variable POST correspondante
	var $setPost;
	var $isHeritage = false;
	var $Triggers;

	//----------------------------------------------//
	//		INITIALISATION			//
	//----------------------------------------------//
	//Constructeur

	function __construct($refMod="",$Data='') {
		//Cree un objet generique correspondant a un resultat de recherche
		$this->Module = $refMod;
		$GLOBALS['Systeme']->Modules[$this->Module]->loadSchema();
		if ($Data!=NULL){
			switch(gettype($Data)) {
				case 'array':
					$this->IdObjClass =$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($Data["ObjectType"]);
					$this->initFromArray($Data);
				break;
				case 'string':
					$this->IdObjClass =$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($Type);
					$this->initFromType($Data);
				break;
			}
		}
	}
	final public function __clone_array($d) {
		if (is_array($d))foreach ($d as $k2=>$d2){
			switch (gettype($d2)){
				case "int":
				case "string":
					$t[$k2] = $d2;
					break;
				case "array":
					$t[$k2] =$this->__clone_array($d2);
					break;
				case "object":
					$t[$k2] = $d2->__deepclone();
					break;
				default:
					$t[$k2] = $d2;
					break;
			}
		}
		return $t;
	}

	final public function getClone() {
		//Methode de clonage
		//On instancie un nouvel objet reflection pour avoir les information sur l objet a cloner.
		$class = get_class($this);
		$r = new ReflectionObject($this);
		//On cree un nouvel objet vide
		$temp = new $class($this->Module,$this->ObjectType);
		$Props = $r->getProperties();
		//On copie l ensemble des proprietes
		foreach ($Props as $p){
			$n = $p->name;
			switch (gettype($this->$n)){
				case "int":
				case "string":
					$temp->$n = $this->$n;
					break;
				case "array":
					$temp->$n =$this->__clone_array($this->$n);
					break;
				case "object":
					$temp->$n = clone $this->$n;
					break;
				default:
					break;
			}
		}
		return $temp;
	}
	function createInstance($refMod,$Data){
		/*
			Parametres : le module, les donnees pour creer
			Resultat : Un objet correspondant exactement a l'objet demande
			*/
		if (!$refMod) return false;
		$GLOBALS['Systeme']->Modules[$refMod]->loadSchema();
		$ClassName = (gettype($Data)=="array") ? $Data["ObjectType"] : $Data;
		$IdObjClass =$GLOBALS['Systeme']->Modules[$refMod]->Db->findByTitle($ClassName);
		$Special = $GLOBALS['Systeme']->Modules[$refMod]->Db->ObjectClass[$IdObjClass]->Class;
		//echo $Special;
		if ($Special!=""){
			//Le cas d une class etendue
			require_once($Special);
			$Class = new $ClassName($refMod,$Data);
		}else{
			$Class = new genericClass($refMod,$Data,true);
		}
		return $Class;
	}


	//Initialisation par rapport a un type du schema
	function initFromType($Type){
		//On recupere le type pr creer des proprietes vides a laide du schema
		if ($this->Module=="") return false;
		$GLOBALS['Systeme']->Modules[$this->Module]->loadSchema();
		$this->IdObjClass =$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($Type);
		$this->ObjectType = $Type;
		if ($GLOBALS['Systeme']->isModule($this->Module)!=""&&is_object($GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]))$Schema=$GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->getSchema();
		if (is_array($Schema['Properties']))foreach ($Schema['Properties'] as $Key=>$Prop) {
			//Priorites de langage
			$Special = $Prop["special"];
			if ($GLOBALS["Systeme"]->User->Admin&&$Special=="multi"){
				$Tab[$Key]="";
				foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Cod=>$Lang) {
					if (!$Lang["DEFAULT"])$Tab[$Cod."-".$Key] = "";
				}
			}else{
				$Tab[$Key]="";
			}
		}
		$Tab['ObjectType']=$Type;
		$this->initFromArray($Tab);
		if ($this->isHeritage) {
			$Result = $this->getHeritagesProp();
			if (is_array($Result)) $this->initHeritages($Result);
		}
	}

	function initHeritages($Tab) {
		$this->Heritages = $Tab;
		for ($i=0;$i<sizeof($Tab);$i++) {
			$this->Heritages[$i]["Valeur"] = $Tab[$i]["Value"];
			$this->Heritages[$i]["SearchOrder"] = "HE";
		}
		/*print_r($this);*/
	}

	function initFromId($Id,$Obj){
		if ($Id==""||$Obj=="") die("REQUETE NON COMPLETE");
		$S = $this->Module."/".$Obj."/".$Id;
		$T = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($S);
		$this->initFromArray($T[0]);
	}

	//Intialisation depuis un tableau
	function initFromArray($Tab) {
		//Initialise l'objet a partir d'un tableau
		if ($Tab["Sys_Module"] != NULL) {$this->Module = $Tab["Sys_Module"];}
		if (!is_array($Tab)) return false;
		foreach ($Tab as $Key=>$Value){
			if (is_array($Value)) $this->$Key = $Value;
			else $this->$Key = stripslashes($Value);
		}
		//On definit les valeurs par defaut
		$Props = $this->Proprietes(false,true);
		if (is_array($Props))foreach ($Props as $P){
			$N = $P["Nom"];
			if ($this->$N==""&&$P["Default"]!=""){
				$this->$N = $P["Default"];
			}
		}
		$this->getInfos();
		//Verif des heritages
		if ($this->isHeritage) $this->initHeritages($Tab["Heritages"]);
		$this->launchTriggers(__FUNCTION__);
	}

	//----------------------------------------------//
	// METHODE INTERROGATION PUBLIQUE		//
	//----------------------------------------------//

	function isCurrent(){
		$Process = new Process();
		$Lien = $Process->processVars("Lien");
		if (preg_match("#".$this->ObjectType."\/".$this->Id."\/#",$Lien)){
			return 1;
		}elseif(preg_match("#".$this->ObjectType."\/".$this->Id."$#",$Lien)) {
			return 2;
		}else{
			return false;
		}
	}

	function getIcon() {
		if (!$this->Module) return false;
		$this->IdObjClass = $GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
		$Icon = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Icon;
		if ($Icon=="") $Icon = "/Skins/AdminV2/Img/folder.gif";
		return $Icon;
	}

	//Recuperation des informations de l objectClass de l objet encours
	function getInfos(){
		//Recupere les informations stockes dans ObjectClass, dans le XML
		if ($this->Module=="") {echo "Aucun module associe, annulation de la requete.";}
		if ($this->ObjectType == "") {;echo "Aucun type d'objet associe, annulation de la requete";}
		$R = $GLOBALS['Systeme']->Modules[$this->Module]->Db->getByTitleOrFkey($this->ObjectType);
		//$this->IdObjClass =
		if ($R["Type"]==1) $this->IdObjClass=$R["Num"];
		elseif ($R["Type"]==2){
			$this->IdObjClass=$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($R["Nom"]);
			$this->ObjectType = $R["Nom"];
		}
		if (empty($GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->objRef)){
			$this->Referent = "faux";
			$this->ReferentModule ="faux";
		}else{
			$this->Referent = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->objRef->titre;
			$this->ReferentModule = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->objRef->Module;
		}
		$this->Historique();
                $this->Conditions = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Conditions;
		$this->setPost = $this->ifSetPost();
		$this->isHeritage = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Heritage;
		$this->Display = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Display;
		$Triggers=Array();
		for($i=0;$i<count($GLOBALS["Systeme"]->Modules[$this->Module]->Triggers);$i++)
		{
			if ($GLOBALS["Systeme"]->Modules[$this->Module]->Triggers[$i]->Target== $this->ObjectType) $Triggers[] = $GLOBALS["Systeme"]->Modules[$this->Module]->Triggers[$i];
		}
		$this->Triggers = $Triggers;
	}

	function Etrangeres() {
		return $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Etrangeres;
	}
	function getPropriete($Name){
		$Props = $this->Proprietes();
		for($i=0;$i<sizeof($Props);$i++){
			if ($Props[$i]["Nom"]==$Name)return $Props[$i];
		}
	}
	//REnvoie l'ensemble des proprietes
	function Proprietes($Langue="",$Intern=false){
		//Tableau contenant les proprietes par ordre d'importance et avec toutes les infos necessaires
		// 		if (!sizeof($Props)) {
		$tabProp=$GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Proprietes;
		$i=0;
		$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
		$ListeVars = get_object_vars($this);
		if (array_key_exists($DefaultLanguage,$GLOBALS["Systeme"]->Language)){
			$Prefixes[$DefaultLanguage] = $GLOBALS["Systeme"]->Language[$DefaultLanguage];
		}
		if ($GLOBALS["Systeme"]->User->Admin){
			foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
				if ($DefaultLanguage!=$Lang){
					$Prefixes[$Lang] = $Pref;
				}else{
					$DefaultPrefixe=$Pref;
				}
			}
		}
		if ($Langue!="" && $Langue){
			if (in_array($Langue,$GLOBALS["Systeme"]->Language)){
				foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
					if ($Langue==$Pref){
						$Prefixes[$Lang] = $Pref;
					}
				}
			}
		}
		$SearchOrder = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Cibles;
		//On parcourt donc tout d'abord les objets ayant des SearchOrder
		if (is_array($SearchOrder)) foreach($SearchOrder as $Key=>$Cible){
			if ($Key != "Id"&&(($tabProp[$Key]["adminOnly"]&&$GLOBALS["Systeme"]->User->Admin)||!$tabProp[$Key]["adminOnly"]||$Intern)) {
				$Infos = $tabProp[$Key];
				$Infos['Nom'] = $Key;
				$Infos['Langue'] = $Prefixes[$DefaultLanguage];
				if (strlen($this->$Key) == 0)
				  $Infos['isNull'] = "True";
				else
				  $Infos['isNull'] = "False";
				$Infos['Valeur'] = $this->$Key;
				$Infos['SearchOrder'] = $Cible;
				$Infos['Ref'] = $tabProp[$Key]['Ref'];
				$Infos['Type'] = $tabProp[$Key]['type'];
				$Infos['Filter'] = $tabProp[$Key]['filter'];
                                $Infos['Category'] = $tabProp[$Key]['category'];
                                $Infos['displayType'] = $this->getDisplayType($tabProp[$Key]['type']);
				$Infos['Longueur'] = $tabProp[$Key]['length'];
				if ($tabProp[$Key]['target']!="")
				$Infos['Target'] = $tabProp[$Key]['target'];
				if ($tabProp[$Key]['description']!="")
				$Infos['description'] = $tabProp[$Key]['description'];
				else $Infos['description'] = $Infos['Nom'];
				$Infos['Default'] = $tabProp[$Key]["default"];
				$Props[$i] = $Infos;
				$i++;
				// 					Verification pour le multilingue
				if(is_array($Prefixes)) foreach($Prefixes as $NomPref=>$Prefixe){
					$NomLangue = $Prefixe."-$Key";
					if (array_key_exists($NomLangue,$ListeVars)) {
						// 						if ($Infos["special"]){
						$Props[$i] = $Infos;
						$Props[$i]['Nom'] = $Prefixe."-".$Key;
						$Props[$i]['Langue'] = $Prefixe;
						$Props[$i]['description'] = "$Key ($NomPref)";
						$Props[$i]['Valeur'] = $this->$NomLangue;
						$i++;
					}
				}
			}
		}
		$noSO = $this->Get("NS");
		if(is_array($noSO)){
			foreach ($noSO as $Cible){
				if (($tabProp[$Cible["Nom"]]["adminOnly"]&&$GLOBALS["Systeme"]->User->Admin)||!$tabProp[$Cible["Nom"]]["adminOnly"]||$Intern) {
					$Infos = $tabProp[$Cible["Nom"]];
					//print_r($tabProp[$Cible["Nom"]]);
					$Infos['Nom'] = $Cible["Nom"];

					$Infos['Langue'] = $Prefixes[$DefaultLanguage];
					$Infos['Valeur'] = stripslashes($Cible["Valeur"]);
				if (strlen(stripslashes($Cible["Valeur"])) == 0)
				  $Infos['isNull'] = "True";
				else
				  $Infos['isNull'] = "False";
					$Infos['Default'] = $tabProp[$Cible["Nom"]]["default"];
					if (!empty($tabProp[$Cible["Nom"]]['description']))
					$Infos[$i]['description'] = $tabProp[$Cible["Nom"]]['description'];
					else $Infos['description'] = $Infos['Nom'];
					$Infos['SearchOrder'] = "NO";
					if (!empty($tabProp[$Cible["Nom"]]['target']))
					$Infos['Target'] = $tabProp[$Cible["Nom"]]['target'];
					$Infos['Ref'] = $tabProp[$Cible["Nom"]]['Ref'];
					$Infos['Type'] = $tabProp[$Cible["Nom"]]['type'];
                                        $Infos['displayType'] = $this->getDisplayType($tabProp[$Cible["Nom"]]['type'] );       
                                        $Infos['Category'] = $tabProp[$Cible["Nom"]]['category'];  
					$Infos['Filter'] = $tabProp[$Cible["Nom"]]['filter'];
					$Infos['Longueur'] = $tabProp[$Cible["Nom"]]['length'];
					$Props[$i] = $Infos;
					$i++;
					if(is_array($Prefixes)) foreach($Prefixes as $NomPref=>$Prefixe){
						$NomLangue = $Prefixe."-".$Cible["Nom"];
						if (array_key_exists($NomLangue,$ListeVars)) {
							$Props[$i] = $Infos;
							$Props[$i]['Nom'] = $Prefixe."-".$Cible["Nom"];
							$Props[$i]['Langue'] = $Prefixe;
							$Props[$i]['description'] = $Cible["Nom"]." ($NomPref)";
							$Props[$i]['Valeur'] = $this->$NomLangue;
							$i++;
						}
					}
				}
			}
		}
		//On ajoute egalement un champ Titre pour les proprietes
		if (is_array($Props)) for ($i=0;$i<sizeof($Props);$i++) {
			$Props[$i]["Titre"] = $Props[$i]["Nom"];
		}
		if ($Langue=="") {
			//On recupere le language par defaut
			$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
			$Langue = $GLOBALS["Systeme"]->Language[$DefaultLanguage];
		}
		//Alors il faut renvoyer un tri sur les prorprietes selon la langue
		$Result=Array();
		if (is_array($Props)) for ($i=0;$i<sizeof($Props);$i++) {
			if ($Props[$i]["Langue"]==$Langue) $Result[] = $Props[$i];
		}
		return $Result;
		}

		function SearchOrder($Langue="") {
			if (!in_array($Langue,$GLOBALS["Systeme"]->Language)) {
				//On recupere le language par defaut
				$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
				$Langue = $GLOBALS["Systeme"]->Language[$DefaultLanguage];
			}
			$Prop = $this->Proprietes();
			if (is_array($Prop)) for ($i=0;$i<sizeof($Prop);$i++) {
				if (is_numeric($Prop[$i]["SearchOrder"])&&$Prop[$i]["Langue"]==$Langue) $Result[] = $Prop[$i];
			}
			return $Result;
		}

		function GetFilter() {
			$Prop = $this->Proprietes();
			if (is_array($Prop)) for ($i=0;$i<sizeof($Prop);$i++) {
				if ($Prop[$i]["filter"]) $Result[] = $Prop[$i];
			}
			return $Result;
		}

		//REnvoi l ensemble des proprietes definit par heritage
		function Heritage() {
			// 		$Heritage=false;
			if (is_array($this->Heritages)&&sizeof($this->Heritages))
			{
				foreach ($this->Heritages as $PropHerite)
				{
					$Infos = Array();
					$Infos['Nom'] = $PropHerite["Nom"];
					$Infos['Valeur'] = stripslashes($PropHerite["Valeur"]);
					$Infos['Type'] = $PropHerite['Type'];
					$Infos['SearchOrder'] = "HE";
					$Heritage[] = $Infos;
				}
			}
			return $Heritage;
		}

		//Renvoie les liaisons integrï¿œes enfants
		function IntegratedLinks() {
			$Enfants = $this->typesEnfant();
			foreach ($Enfants as $Enf) {
				if ($Enf["Behaviour"]=="Integrated") {
					$Result[] = $Enf;
				}
			}
			return $Result;
		}

		//Renvoie l ensemble des informations systeme de la donnï¿œe
		//Renvoie l ensemble des informations systeme de la donnï¿œe
		function infoSysteme() {
			// 		if (!sizeof($this->infoSysteme)) {
			$Reserved = $this->Reserved();
			//Construction du tableau de propriete des droits
			$Infos['Nom'] = "Type d'ObjectClass";
			$Infos['Valeur'] = $this->ObjectType;
			$Infos['Type'] = "varchar";
			$infoSysteme[] = $Infos;
			$Infos['Nom'] = "Date de création";
			$Infos['Valeur'] = $Reserved[0]['dateCreate'];
			$Infos['Type'] = "date";
			$infoSysteme[] = $Infos;
			$Infos['Nom'] = "Date de modification";
			$Infos['Valeur'] = $Reserved[0]['dateEdit'];
			$Infos['Type'] = "date";
			$infoSysteme[] = $Infos;
			$U = $GLOBALS["Systeme"]->Modules["Systeme"]->callData("Systeme/User/".$Reserved[0]['userCreate'],0,0,1);
			$C = $Reserved[0]['userCreate'];
			$Infos['Nom'] = "Créé par l'utilisateur";
			$Infos['Valeur'] = $C;
			$Infos['Type'] = "varchar";
			$infoSysteme[] = $Infos;
			$U = $GLOBALS["Systeme"]->Modules["Systeme"]->callData("Systeme/User/".$Reserved[0]['userEdit'],0,0,1);
			$C = $Reserved[0]['userEdit'];
			$Infos['Nom'] = "Edité par l'utilisateur";
			$Infos['Valeur'] = $C;
			$Infos['Type'] = "int";
			$infoSysteme[] = $Infos;
			// 		}
			return $infoSysteme;
		}

		//Renvoie l ensemble des type d objectClass enfant
		function typesEnfant(){
			$Enfants = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->parentOf;
			if (is_array($this->AddChild)) foreach ($this->AddChild as $Child){
				$Enfants[] = $Child;
			}
			$typesEnfant = $Enfants;
			return $typesEnfant;
		}

		//Renvoie l ensemble des type d objectClass enfant
		function Functions(){
			$Funcs = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->Functions;
			if (is_array($Funcs)) foreach ($Funcs as $Name=>$F){
				$Temp = $F;
				$Temp["Nom"] = $Name;
				$Functions[] = $Temp;
			}
			return $Functions;
		}

		//Renvoie les droits de la donnï¿œe en cours
		function Droits() {
			//Construction du tableau de propriete des droits
                        $C = $this->uid;
			$Infos['Nom'] = "Proprietaire";
			$Infos['Valeur'] = $C;
			$Infos['Type'] = "varchar";
			$Droits[] = $Infos;
		        $C = $this->gid;
			$Infos['Nom'] = "Groupe";
			$Infos['Valeur'] = $C;
			$Infos['Type'] = "varchar";
			$Droits[] = $Infos;
			$Infos['Nom'] = "Umod";
			$Infos['Valeur'] = $this->umod;
			$Infos['Type'] = "int";
			$Droits[] = $Infos;
			$Infos['Nom'] = "Gmod";
			$Infos['Valeur'] = $this->gmod;
			$Infos['Type'] = "int";
			$Droits[] = $Infos;
			$Infos['Nom'] = "Omod";
			$Infos['Valeur'] = $this->omod;
			$Infos['Type'] = "int";
			$Droits[] = $Infos;
			return $Droits;
		}

		//Renvoie l ensemble des types de parents possibles
		function typesParent(){
			$Parents = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->childOf;
			$typesParent = $Parents;
			return $typesParent;
		}

		//REnvoie l historique de la requete de l objet en cours
		function Historique(){
			//Construit l'url et edite l'historique
			$Url = $this->Module;
			$Nbhisto = count($this->Historique)-1;
			//Construction de l'url
			for ($i=0;$i<=$Nbhisto;$i++){
				$this->Historique[$i]['Num'] = $i;
				//On verifie si l'objectClass n'est pas default
				$Obc = ($i==0||$this->Historique[$i-1]['ObjectType']==$this->Historique[$i]['ObjectType'])?$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($this->Historique[$i]['ObjectType']):$Obc;
				if (!$Obc->Default)$Url.='/'.$this->Historique[$i]['ObjectType'];
				$this->Historique[$i]['objectUrl'] = $Url;
				$Url.='/'.$this->Historique[$i]['Id'];
				$this->Historique[$i]['getUrl'] = $Url;
				if ($i==count($this->Historique)-1) $this->beforeUrl = $Url;
				if (empty($kUrl)) $kUrl = $this->Historique[$i]['Url'];
				else $kUrl .= '/'.$this->Historique[$i]['Url'];
				$this->Historique[$i]['quickUrl'] = $kUrl;
			}
			$this->firstObjType = ($i>0)?$this->Historique[$i]['ObjectType']:$this->ObjectType;
			$this->menuUrl = (($kUrl!="")?$kUrl.'/':'').$this->Url;
			$Obc = $GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			if (!$Obc->Default)$Url.='/'.$this->ObjectType;
			$this->objectUrl = $Url;
			$this->Level = $i+1;
			if ($this->Id!="")$Url.='/'.$this->Id;
			$this->myUrl = $Url;
			return $this->Historique;
		}

		function getUrl() {
			$Url = $this->Module;
			$Nbhisto = sizeof($this->Historique())-1;
			for ($i=0;$i<=$Nbhisto;$i++){
				$this->Historique[$i]['Num'] = $i;
				if ($i==0) $this->firstObjType = $this->Historique[$i]['ObjectType'];
				$Url.='/'.$this->Historique[$i]['ObjectType'];
				$this->Historique[$i]['objectUrl'] = $Url;
				$Url.='/'.$this->Historique[$i]['Id'];
				$this->Historique[$i]['getUrl'] = $Url;
				if ($i==count($this->Historique)-1) $this->beforeUrl = $Url;
				if (empty($kUrl)) $kUrl = $this->Historique[$i]['Url'];
				else $kUrl .= '/'.$this->Historique[$i]['Url'];
				$this->Historique[$i]['quickUrl'] = $kUrl;
			}
			//		if (!$Nbhisto) $this->Historique = Array();
			if (empty($this->firstObjType)) $this->firstObjType = $this->ObjectType;
			$this->menuUrl = $kUrl.'/'.$this->Url;
			$Url.='/'.$this->ObjectType;
			$this->objectUrl = $Url;
			$this->Level = $i+1;
			$Url.='/'.$this->Id;
			$this->myUrl = $Url;
			return $Url;
		}

		function pastHistory(){
			//Construit l'url et edite l'historique
			$this->Historique();
			$Url = $this->Module;
			$Nbhisto = count($this->Historique)-1;
			//print_r($this->Historique);
			for ($i=0;$i<=$Nbhisto;$i++){
				if ($this->Historique[$i]['ObjectType']!=$this->ObjectType){
					$Histo[] = $this->Historique[$i];
				}
			}
			return $Histo;
		}

		function currentHistory(){
			//Construit l'url et edite l'historique
			$this->Historique();
			$Url = $this->Module;
			$Nbhisto = count($this->Historique)-1;
			//print_r($this->Historique);
			for ($i=0;$i<=$Nbhisto;$i++){
				if ($this->Historique[$i]['ObjectType']==$this->ObjectType){
					$Histo[] = $this->Historique[$i];
				}
			}
			return $Histo;
		}

		function getFirstSearchOrder(){
			return $this->Get("S1");
		}

		function getSecondSearchOrder(){
			return $this->Get("S2");
		}

		function isReference(){
			$i=$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$tabRef=$GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$i]->Reference[0];
			if (empty($tabRef)) return "FAUX";
			else return $tabRef["module"]."/".$tabRef["champ"];
		}


		function Reserved(){
			$Reserved[0]['dateCreate'] = date("d/m/Y H:i:s",$this->tmsCreate);
			$Reserved[0]['dateEdit'] = date("d/m/Y H:i:s",$this->tmsEdit);
			$Reserved[0]['userCreate'] = $this->userCreate;
			$Reserved[0]['userEdit'] = $this->userEdit;
			$Ref = $this->isReference();
			$Reserved[0]['reference'] = $Ref;
			return $Reserved;
		}

		function isReflexive(){
			if (!$this->Module) {
				echo "AUCUN MODULE DE DEFINIT";
				return false;
			}
			if ($GLOBALS["Systeme"]->Modules[$this->Module]->Db->isReflexive($this->ObjectType)){
				return 1;
			}else return 0;
		}

		function urlReflexive(){
			if ($GLOBALS["Systeme"]->RegVars["lastObject"]==$this->ObjectType){
				return $this->ObjectType;
			}else return $this->ObjectType."/1/".$this->ObjectType;

		}

		//----------------------------------------------//
		//		EDITION				//
		//----------------------------------------------//

		function RecursiveErase(){
			// 		$this->typesEnfant();
			//print_r($this->typesEnfant);
			/*	if (is_array($this->typesEnfant())) foreach ($this->typesEnfant() as $Type)
			 {
			 $Requete = $this->ObjectType."/".$this->Id."/".$Type["Titre"];
			 $Res = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($Requete);
			 if (is_array($Res)) foreach($Res as $Child)
			 {
				if (!empty($Child["Id"]) && !empty($Child["ObjectType"]))
				{
				$ChildObj = new genericClass($this->Module);
				$ChildObj->initFromArray($Child);
				$ChildObj->RecursiveErase();
				}
				}
				}*/
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			if ($NumObj<0)return false;
			$Flag = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->Erase($this);
			return $Flag;
		}


		function Delete(){
			//Programme la suppression de l'objet courant
			$Flag = $this->RecursiveErase();
			//$Flag = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$Obj]->Erase($this);
			$this->launchTriggers(__FUNCTION__);
			return $Flag;
		}


		function deleteFKey($class,$id){
			//Programme la suppression du clef etrangere et peut Ãªtre de l'objet qui y est associe
			$this->Parents[]=Array('Titre'=>$class,'Id'=>$id,"Action"=>0);
		}
		function removeParent($class,$id){
			//Programme la suppression du clef etrangere et peut Ãªtre de l'objet qui y est associe
			$this->addFKey($class,$id,0);
		}


		function changeFkey($Class,$Nid,$Oid='',$formId){
			//Programme la modification d'une clef etrangere
			$this->Parents[] = Array("Titre"=>$Class,
					"AncienId"=> $Oid,
					"NouvelId"=> $Nid,
					"Action"=>1,
					"numAssoc"=>$formId);
		}

		function AddParent($Q="",$SpeFKey=""){
			if (is_object($Q)) $Q = $Q->myUrl;
			if (!$Q) return false;
			$I=$GLOBALS["Systeme"]->Modules[$this->Module]->splitQuery($Q);
			if ($I[0]["Type"]=="Child") $Q = $this->Module."/".$I[sizeof($I)-2]["DataSource"]."/".$I[sizeof($I)-2]["Value"];
			else $Q = $this->Module."/".$I[sizeof($I)-1]["DataSource"]."/".$I[sizeof($I)-1]["Value"];
			$ExplQ = explode ("/",$Q);
			if (sizeof($ExplQ)<3) return false;
			$NbQ = sizeof($ExplQ)-1;

			$this->addFkey($ExplQ[$NbQ-1],$ExplQ[$NbQ],2,$SpeFKey);
		}

		function DelParent($Q=""){
			if (is_object($Q)){
				$Q = $Q->myUrl;
			}
			if (!$Q) return false;
			$ExplQ = explode ("/",$Q);
			if (sizeof($ExplQ)<3) return false;
			$NbQ = sizeof($ExplQ)-1;
			$this->addFkey($ExplQ[$NbQ-1],$ExplQ[$NbQ],0);
		}

		function resetParents($Class) {
			$Parents = $this->getParents($Class);
			unset($this->Parents);
			for ($i=0;$i<sizeof($Parents);$i++) {
				$this->addFKey($Parents[$i]->ObjectType,$Parents[$i]->Id,0);
				//if (sizeof($this->Parents[$i])>1)$this->Parents[$i]["Action"] = 0;
			}
		}

		//ACTION
		//2 AJOUT
		//1 MODIFICATION
		//0 SUPPRESSION
		function addFkey($Class,$Nid,$Action=2,$SpeFKey=""){
			//Ajoute une nvelle clef etrangere
			if ($Class==$this->Module) $Class=$this->ObjectType;
			$this->Parents[] = Array("Titre"=>$Class,"Id"=> $Nid,"Action"=>$Action);
			$this->Parents[count($this->Parents)-1]["Fkey"] = (empty($SpeFKey)) ? $Class:$SpeFKey;
		}


		function addChild($Type,$Id){
			//Associe un enfant existant Ã  l'objet courant
			$Enfant = new genericClass($this->Module);
			$Enfant->initFromId($Id,$Type);
			$Enfant->addFkey($this->ObjectType,$this->Id);
			$Enfant->Save();
		}


		function createChild(){
			//CrÃ©Ã© un enfant Ã  l'objet courant
			$Vars=Process::ProcessQuery("Form_");
			$Enfant = new genericClass($this->Module,$Vars);
			$Enfant->addFkey($this->ObjectType,$this->Id);
			$Enfant->Save();
		}


		function Get($Data,$Nom=false) {
			//Appelle une methode pour renvoyer une propriete ou un enfant de l'objet
			$this->launchTriggers(__FUNCTION__,$Data);
			if ($Data=="NS"){
				$GLOBALS['Systeme']->Modules[$this->Module]->loadSchema();
				$i=$GLOBALS['Systeme']->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
				$tabProp=$GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$i]->Proprietes;
				$int=0;
				if (is_array($tabProp))  foreach ($tabProp as $Key=>$Propriete){
					if (!$Propriete["searchOrder"]) {
						$Tab[$int]['Nom'] = $Key;
						$Tab[$int]['Valeur'] = $this->$Key;
						$int++;
					}
				}
				return $Tab;
			}
			if (preg_match("#S[0-9]+#",$Data)){
				if ($Data=="S0") return $this->Id;
				//Si on a un nombre precede d'un S, c'est donc forcement un SearchOrder:
				$Data = substr($Data,1,count($Data));
				$So = $this->SearchOrder();
				if (sizeof($So)){
					foreach ($So as $S) {
						if ($S["searchOrder"]==$Data&&$S["Titre"]!="Url") $Key = $S["Titre"];
					}
				}
				if (!$Key) return false;
				return (!$Nom) ? $this->$Key:$Key ;
			}
			//On verifie si c est un mot reserve
			if ($Data=="Id") return $this->Id;
			//Sinon, on recherche le type: si c'est une clef etrangere, on recherche les enfants
			/*		echo "---------------$Data--------------\r\n";
			print_r($this);*/
			if (is_array($this->Etrangeres()))if (array_key_exists($Data,$this->Etrangeres())) return $this->getChilds($Data);
			//Sinon, on renvoie la propriete recherchee
			foreach ($this->Proprietes() as $Propriete){
				// 			echo "VAR $Data TYPE ".$Propriete['Nom']."\r\n";
				if($Propriete['Nom'] == $Data) {
					switch ($Propriete['Type']) {
						case "txt":
						case "bbcode":
						case "text":
							$temp = new charUtils();
							$temp->ChildObjects[] = $this->$Data;
							$temp->Beacon = "UTIL";
							$temp->Vars = "BBCODE";
							return $temp->affich();
							break;
							/*					case "raw":
							 return nl2br($this->$Data);
							 break;*/
						case "html":
						default:
							return $this->$Data;
							break;
					}
				}
			}
			//Donc pas une propriete , donc il s agit d une variable
			return $this->$Data;
			//Si on a pas trouve la propriete, elle n'existe pas et on renvoie une rreur
			return false;
		}
		//----------------------------------------------//
		//		HERITAGE			//
		//----------------------------------------------//

		function launchTriggers($function_name,$param="")
		{
			/*
			 Parametres : Le nom de la fonction appelante, un parametre si necessaire
			 Resultat : true si tout s'est bien passe, false sinon
			 Declenchement des evenements associes dans Modules/Module.Name/Module.Name.Actions
			 */
			//Copie du tableau des triggers
			$KnownEvents = Array();
			for ($i=0;$i<count($this->Triggers);$i++){
				if (is_array($this->Triggers[$i]->Functions))foreach ($this->Triggers[$i]->Functions as $K=>$F){
					$KnownEvents[$this->Triggers[$i]->Functions[$K]->Event][] = $this->Triggers[$i]->Functions[$K];
				}
			}
			$v = Array();
			switch(strtolower($function_name)){
				case "initfromarray":
					if ( in_array("Load",array_keys($KnownEvents) )) $v = array_merge($v,$KnownEvents["Load"]);
					break;
				case "get":
					//TODO : Mode de recherche d'un seul champ
					if ( in_array("Get",array_keys($KnownEvents) )) $v = array_merge($v,$KnownEvents["Get"]);
					break;
				case "set":
					//TODO : Mode de modification d'un seul champ
					if ( in_array("Load",array_keys($KnownEvents) )) $v = array_merge($v,$KnownEvents["Set"]);
					break;
				case "delete":
					if ( in_array("Delete",array_keys($KnownEvents) )){
						$v = array_merge($v,$KnownEvents["Delete"]);
					}
					break;
				case "save":
					//NEW
					if ($this->tmsCreate==$this->tmsEdit){
						if ( in_array("New",array_keys($KnownEvents) )) $v = array_merge($v,$KnownEvents["New"]);
					}
					else if ( in_array("Save",array_keys($KnownEvents) )) $v = array_merge($v,$KnownEvents["Save"]);
					break;
			}
			for ($i=0;$i<sizeof($v);$i++){
				$v[$i]->Execute($this);
			}
		}

		//Renvoie l ensemble des type dobjectClass enfant concernï¿œs par l'heritage
		function typesEnfantHeritage(){
			$EnfantsTemp = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->parentOf;
			if (is_array($EnfantsTemp)) foreach ($EnfantsTemp as $Child){
				if ($Child["Heritage"]==1) $Enfants[] = $Child;
			}
			if (is_array($this->AddChild)) foreach ($this->AddChild as $Child){
				if ($Child["Heritage"]==1) $Enfants[] = $Child;
			}
			return $Enfants;
		}

		//Renvoie l ensemble des type dobjectClass enfant concernï¿œs par l'heritage
		function typesParentHeritage(){
			$EnfantsTemp = $GLOBALS['Systeme']->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->childOf;
			if (is_array($EnfantsTemp)) foreach ($EnfantsTemp as $Child){
				if ($Child["Heritage"]==1) $Enfants[] = $Child;
			}
			if (is_array($this->AddChild)) foreach ($this->AddChild as $Child){
				if ($Child["Heritage"]==1) $Enfants[] = $Child;
			}
			return $Enfants;
		}
		//renvoie les regles dheritages dont cet objet est la cible
		function getHeritagesProp(){
			$HeritsParents = $this->typesParentHeritage();
			if (sizeof($HeritsParents))foreach($HeritsParents as $Par) {
				$Temp = $this->getParents($Par["Titre"]);
				if (is_array($Temp))foreach ($Temp as $Rs) {
					$Parents[] = $Rs;
				}
			}
			//On recuperer maintenant les regles d heritages
			if (sizeof($Parents))foreach ($Parents as $T) {
				$ObjType = $T["Titre"];
				if ($ObjType=="") $ObjType=$T["ObjectType"];
				$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($ObjType);
				if ($NumObj==-1) return;
				$Result= $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->GetHeritages($T["Id"],true);
				if (is_array($Result))foreach ($Result as $Res) {
					$Res["ObjectClass"] = $ObjType;
					$Results[] = $Res;
				}
			}
			if (is_array($Results)&&$GLOBALS["Systeme"]->User->Admin) {
				foreach ($Results as $r) {
					//On doit partager le resultat en toutes les langues
					foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Key=>$Lang) {
						$TempResults = $r;
						$TempResults["Langue"]=$Key;
						if($GLOBALS["Systeme"]->DefaultLanguage!=$Lang["TITLE"]){
							$TempResults["Nom"] = $Key."-".$TempResults["Field"];
							$TempResults["Titre"] = $TempResults[$Key."-Titre"];
						}else{
							$TempResults["Nom"] = $TempResults["Field"];
						}
						$TR[] = $TempResults;
					}
				}
				$Results = $TR;
			}
			//Initialisation des proprietes
			if (is_array($Results))foreach ($Results as $T) {
				unset($Temp);
				$Temp["Nom"] = $T["Field"];
				$Temp["description"] = $T["Titre"];
				$Temp["Valeur"] = $T["Value"];
				$Temp["Type"] = $T["Type"];
				$Temp["Langue"] = $T["Langue"];
				$Temp["SearchOrder"] = "HE";
				// 			$this->Proprietes[] = $Temp;
			}
			return $Results;
		}

		//renvoie les regles dheritages qui propage des proprietes
		function getHeritages(){
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$Result= $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->GetHeritages($this->Id);
			return $Result;
		}

		function getHeritageById($Id){
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$Result= $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->GetHeritages($this->Id);
			foreach($Result as $herit){
				if ($herit["Id"]==$Id) $Return[]= $herit;
			}
			return $Return;
		}

		//Ajout d une regle d'heritage
		function addHeritage($Enfant, $NomProp,$TypeProp,$Group,$Level,$Order){
			//Creation du tableau
			$Heritage["Parent"] = $this->ObjectType;
			$Heritage["NomPropriete"] = $NomProp;
			$Heritage["TypePropriete"] = $TypeProp;
			$Heritage["Group"] = $Group;
			$Heritage["Level"] = $Level;
			$Heritage["Order"] = $Order;
			$Heritage["Id"] = $this->Id;
			$Heritage["Enfant"] = $Enfant;
			//Creation de la requete
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$Heritage = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->addHeritage($Heritage);
			$j = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($Heritage["Enfant"]);
			//$GLOBALS["Systeme"]->Modules[$this->Module]->Db->RecursiveChk($Heritage["Enfant"],$Heritage);
		}

		//Ajout d une regle d'heritage
		function addHeritageValue($Nom, $Lang,$Titre,$Value){
			//Creation du tableau
			$Heritage["Field"] = $Nom;
			$Heritage["Lang"] = $Lang;
			$Heritage["Titre"] = $Titre;
			$Heritage["Value"] = $Value;
			$Heritage["Id"] = $this->Id;
			//Creation de la requete
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$Heritage = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->addHeritageValue($Heritage);
			$j = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($Heritage["Enfant"]);
			//$GLOBALS["Systeme"]->Modules[$this->Module]->Db->RecursiveChk($Heritage["Enfant"],$Heritage);
		}

		function removeHeritage($Id){
			$Heritage = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->removeHeritage($Id);
		}

		function changeHeritage($Id,$Field,$Type,$Target,$Group,$Level,$Order){
			//Creation du tableau
			$Heritage["Field"] = $Field;
			$Heritage["Target"] = $Target;
			$Heritage["Type"] = $Type;
			$Heritage["Group"] = $Group;
			$Heritage["Level"] = $Level;
			$Heritage["Order"] = $Order;
			$Heritage["ObjId"] = $this->Id;
			$Heritage = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->changeHeritage($Heritage,$Id);
		}
		function changeHeritageValue($Id,$Titre,$Value,$Lang){
			//Creation du tableau
			$Heritage["Titre"] = $Titre;
			$Heritage["Value"] = $Value;
			$Heritage["Lang"] = $Lang;
			$Heritage = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->changeHeritageValue($Heritage,$Id);
		}
		//----------------------------------------------//
		//		VERIFICATION			//
		//----------------------------------------------//
		function Check($Nom,$Value="",$Type="") {
			//Verifie la valeur dun champ (ex: mot de passe)
			if (is_string($Nom)){
				$Props = $this->Proprietes(false,true);
				for ($i=0;$i<sizeof($Props);$i++){
					if ($Props[$i]["Nom"]==$Nom){
						$Prop = $Props[$i];
					}
				}
			}elseif (is_array($Nom)){
				$Prop = $Nom;
			}
			$error=1;
			//Verification en fonction du type
			switch ($Prop["Type"]) {
				case "password":
					if ($Type=="Conformity"){
						if ($this->$Prop["Titre"]==""){
							$error=0;
						}
					}else{
						if ($Value!=""&&$this->$Prop["Titre"]!=""){
							if (md5($Value)!=$this->$Prop["Titre"]) {
								$e["Message"] = "Le mot de passe ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas valide";
								$e["Prop"] = $Prop["Titre"];
								$this->AddError($e);
								$error=0;
							}
						}else{
							$error=0;
						}
					}
					break;
				case "mail":
					if (!Process::processVars("Utils::isMail(".$this->$Prop["Titre"].")")&&$this->$Prop["Titre"]!=""){
						$e["Message"] = "L'adresse mail du champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas valide";
						$e["Prop"] = $Prop["Titre"];
						$this->AddError($e);
						$error=0;
					}
					break;
				case "date":

					if ((!Process::processVars("Utils::isDate(".$this->$Prop["Titre"].")")&&strlen($this->$Prop["Titre"])>1&&!is_numeric($this->$Prop["Titre"]))||(is_numeric($this->$Prop["Titre"])&&strlen($this->$Prop["Titre"])<1)) {
						$e["Message"] = "La date du champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas valide. Format : jj/mm/aaaa";
						$e["Prop"] = $Prop["Titre"];
						$this->AddError($e);
						$error=0;
					}
					break;
				case "int":
					if (is_int($this->$Prop["Titre"])&&$this->$Prop["Titre"]!=""){
						$e["Message"] = "La valeur du champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas un entier";
						$e["Prop"] = $Prop["Titre"];
						$this->AddError($e);
						$error=0;
					}
					break;
				case "string":
					if (is_string($this->$Prop["Titre"])&&$this->$Prop["Titre"]!=""){
						$e["Message"] = "La valeur du champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas une chaÃ®ne de caractÃšre valide";
						$e["Prop"] = $Prop["Titre"];
						$this->AddError($e);
						$error=0;
					}
					break;
			}
			//Verification en fonction des attributs
			if ($Prop["obligatoire"]==1){
				if (addslashes($this->$Prop["Titre"])==""&&$Prop["Type"]!="file"){
					$e["Message"] = "Le champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." est obligatoire.";
					$e["Prop"] = $Prop["Titre"];
					$this->AddError($e);
					$error=0;
				}elseif ($Prop["Type"]=="file"){
				 if (!is_array($_FILES["Form_".$Prop["Titre"]."_Upload"])&&$this->$Prop["Titre"]==""){
				 	$e["Message"] = "Le champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." est obligatoire.";
				 	$e["Prop"] = $Prop["Titre"];
				 	$this->AddError($e);
					 $error=0;
				 }
				}
			}
                        if ( $Prop["unique"]==1 && $this->Id=="") {
                            $Res = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($this->Module."/".$this->ObjectType."/".$Prop["Titre"]."=".$this->$Prop["Titre"]);
                            if ( !empty($Res) ) {
                                $this->AddError(array("Message" => "Ce ".$Prop["Titre"]." est d&eacute;ja utilis&eacute;",
                                                      "Prop" => $Prop["Titre"]));
                                $error = 0;
                            }
                        }
                        if ( $Prop["unique"]==1 && $this->Id!="") {
                            $Res = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($this->Module."/".$this->ObjectType."/".$Prop["Titre"]."=".$this->$Prop["Titre"]);
                            if ( !empty($Res) ) {
                               foreach($Res as $Test)
                               {
                                  if ( $Test["Id"] != $this->Id ) {
                                $this->AddError(array("Message" => "Ce ".$Prop["Titre"]." est d&eacute;ja utilis&eacute;",
                                                      "Prop" => $Prop["Titre"]));
                                $error = 0;
                               }
                              }
                            }
                        }
			return $error;
		}

		function ModifierDroits($Recursif=0,$Pid="",$Gid="",$Umod="",$Gmod="",$Omod="")
		{
			/*		if ($Recursif)
			 {
			 $this->typesEnfant();
			 if (is_array($this->typesEnfant())) foreach ($this->typesEnfant() as $Type)
			 {
				$Requete = $this->ObjectType."/".$this->Id."/".$Type["Titre"];
				$Res = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($Requete);
				if (is_array($Res)) foreach($Res as $Child)
				{
				if (!empty($Child["Id"]) && !empty($Child["ObjectType"]))
				{
				$ChildObj = new genericClass($this->Module);
				$ChildObj->initFromArray($Child);
				$ChildObj->ModifierDroits(1,$Pid,$Gid,$Umod,$Gmod,$Omod);
				}
				}
				}
				}*/
			$NumObj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($this->ObjectType);
			$Flag = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$NumObj]->ChangeRights($this->Id,$Pid,$Gid,$Umod,$Gmod,$Omod);
		}

		function Set($Prop,$newValue) {
		$this->launchTriggers(__FUNCTION__);
		$Props = $this->Proprietes(false,true);
		for ($i=0;$i<sizeof($Props);$i++){
			if ($Props[$i]["Nom"] == $Prop) {
			switch ($Props[$i]["Type"]) {
				case "password":
				if ($newValue!="*******") $newValue = md5($newValue);
				else return false;
				break;
				case "file":
				if ($this->fileUpload(Array("Nom"=>$Prop),$newValue))return false;
				if ($newValue=="UPLOAD") return false;
				break;
			}
			}
		}
		if (is_string($newValue)) $newValue = trim($newValue);
		$this->$Prop = $newValue;
		return true;
		}
	
	
	
		function normalizeFileName($chaine) {
		//On enleve les accents
		$chaine = strtr($chaine,  "ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ","aaaaaaaaaaaaooooooooooooeeeeeeeecciiiiiiiiuuuuuuuuynn" );
		//On remplace tous ce qui n est pas une lettre ou un chiffre par un _
		$chaine = preg_replace('/([^.a-z0-9]+)/i', '_', $chaine);
		$chaine = strtolower($chaine);
		//         $chaine = preg_replace('#(.+)\.([a-z]{3})#i','$1-'.time().'.$2',$chaine);
		return $chaine;
		}
	
		function fileUpload($Prop,$value="")
		{
		if (!empty($_FILES[$value]['name'])) $FileArray=$_FILES[$value];
		if (!empty($_FILES['Form_'.$Prop["Nom"]]['name'])) $FileArray=$_FILES['Form_'.$Prop["Nom"]];
		if (!empty($_FILES['Form_'.$Prop["Nom"]]['name'])) $FileArray=$_FILES['Form_'.$Prop["Nom"]];
		if (!empty($_FILES['Form_'.$Prop["Nom"].'_Upload']['name'])) $FileArray=$_FILES['Form_'.$Prop["Nom"].'_Upload'];
		if (!empty($_FILES['Filedata'])) $FileArray=$_FILES["Filedata"];
		if (empty($FileArray)) return false;
		$fichier = basename($FileArray['name']);
		//On definit l emplacement du fichier upload par defaut
		$Usr = ($this->Get("Fake_User_Upload")) ? $this->Get("Fake_User_Upload"):$GLOBALS["Systeme"]->User->Id;
		if ($this->Module=="Explorateur"&&$this->ObjectType=="Insert"){
			$dossier = "Home/$Usr/".$this->get("Destination")."/";
		}else{
			$dossier = "Home/$Usr/".$this->Module."/".$this->ObjectType."/";
		}
		if (!file_exists($dossier)) fileDriver::mk_dir($dossier);
		//On verifie si la taille ne depasse pas le seuil autorise
		$taille_maxi = 1000000000;
		$taille = filesize($FileArray['tmp_name']);
		$extension = strrchr($fichier, '.');
	
		if ($this->Type=="Media"){
			$extensions = array('.png', '.gif', '.jpg', '.jpeg','.flv','.bmp','.tiff');
			//Ensuite on teste
			if(!in_array(strtolower($extension), $extensions))
			{
			return false;
			}
		}
		$fichier = $this->normalizeFileName($fichier);
		$file_name = basename($fichier,$extension);
		if($taille>$taille_maxi){
			$GLOBALS["Systeme"]->Error->sendWarningMsg(5);
		}
	
		if (!empty($Vars[$Prop["Nom"]])) {
			if(!move_uploaded_file($FileArray['tmp_name'], $Vars[$Prop["Nom"]])) $GLOBALS["Systeme"]->Error->sendWarningMsg(4);
		}else{
			$d = "";
			while (file_exists($dossier.$file_name.$d.$extension))
			{
			$d++;
			}
			if(!move_uploaded_file($FileArray['tmp_name'], $dossier.$file_name.$d.$extension)){
			$GLOBALS["Systeme"]->Error->sendWarningMsg(41);
			}
			$N = $Prop["Nom"];
			$this->$N=$dossier.$file_name.$d.$extension;
			return true;
		}
		unset($_FILES['Form_'.$Prop["Nom"].'_Upload']);
		unset($_FILES['Form_'.$Prop["Nom"]]);
		return false;
		}
	
		function Save() {
		//Sauvegarde l'enregistrement en cours dans la base de donnees
		//On traite les dictionnaires automatiques
		foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
			foreach($this->Proprietes($Pref) as $Prop){
				switch ($Prop["Type"]){
					case "file":
						$this->fileUpload($Prop,$Prop["Valeur"]);
					break;
					case "mail":
						if (!Process::processVars("Utils::isMail(".$this->$Prop["Titre"].")")&&$this->$Prop["Titre"]!=""){
							$e["Message"] = "L'adresse mail du champ ".(($Prop["description"]!="")?$Prop["description"]:$Prop["Titre"])." n'est pas valide";
							$e["Prop"] = $Prop["Titre"];
							$this->AddError($e);
							$error=0;
						}
					break;
					case "autodico":
						$Nom = $Prop["Nom"];
						$Valeur = $this->$Nom;
						$Query=$this->Module."/".$Prop["Target"];
						$Tab = $GLOBALS["Systeme"]->Modules[$this->Module]->callData($Query);
						if(!is_array($Tab)) $Id= 1;
						else{
							$maybeId = 0;
							foreach ($Tab as $Dico){
							if ($Dico["Id"]>$maybeId) $maybeId = $Dico["Id"];
							if ($Dico["Type"]==$Valeur){
								$Id = $Dico["Id"];
								$Test = true;
							}
							}
						}
						if ($Test==false){
							if (empty($Id)) $Id = $maybeId+1;
							$Generic = new genericClass($this->Module);
							$Generic->initFromType($Prop["Target"]);
							$Generic->Id = $Id;
							$Generic->Type = $Valeur;
							$Generic->Save();
						}
						$this->$Nom = $Id;
					break;
					case "float":
						$Nom = $Prop["Nom"];
						if ($this->$Nom=="0")
						$this->$Nom="0.0";
					break;
					case "date":
						$Nom = $Prop["Nom"];
						if (preg_match("#^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})\ ([0-9]{2})\:([0-9]{2})\:([0-9]{2})$#",$this->$Nom,$out)){
							$this->$Nom = mktime($out[4],$out[5],$out[6],$out[2],$out[1],$out[3]);
						}
						if (preg_match("#^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$#",$this->$Nom,$out)){
							$this->$Nom = mktime(0,0,0,$out[2],$out[1],$out[3]);
						}
					break;
				}
			}
		}
		//if (sizeof($this->Error))return false;
		//Si il n a pas ï¿œtï¿œ dï¿œfini de paren
		//print_r($this->Parents);
		//print_r($this->typesParent());
		if (is_array($this->typesParent())) foreach ($this->typesParent() as $Par){
			//Recherche de la clef etrangere parmis les parents
			$Parents = $this->getParentsFromType($Par["Titre"]);
			if (is_array($Parents)) foreach ($Parents as $K=>$Fkey){
			if ($Fkey["Action"]=="") $Action = "2"; else $Action = $Fkey["Action"];
			if ($Par["Target"]!="Id") {
				//Alors il faut recuperer la bonne valeur
				$Enfant = genericClass::createInstance($this->Module,false);
				$Enfant->initFromId($Fkey["Id"],$Fkey["Titre"]);
				$Fkey["Id"] = $Enfant->get($Par["Target"]);
			}
			$NewParent[] = $Fkey;
			}
		}
		$this->Parents = $NewParent;
		//On met a jour les heritages
		if (sizeof($this->Heritages)){
			for ($i=0;$i<sizeof($this->Heritages);$i++){
			$Name = $this->Heritages[$i]["Nom"];
			$this->Heritages[$i]["Valeur"] = $this->$Name;
			$this->Heritages[$i]["Value"] = $this->$Name;
			}
		}
		$Results = $GLOBALS['Systeme']->Modules[$this->Module]->Db->Query($this);
		unset($this->Parents);
		$this->initFromArray($Results);
		$this->launchTriggers(__FUNCTION__);
		}
		function getParentsFromType($Type) {
			if (is_array($this->Parents))foreach ($this->Parents as $P) {
				if (is_array($P))if ($P["Titre"]==$Type) $Result[] = $P;
				if (is_object($P))if ($P->Titre==$Type) $Result[] = $P;
			}
			return $Result;
		}

		function Verify() {
			$error = 1;
			unset($this->Error);
			//Lancement de la verification des prorpietes
			$Props = $this->Proprietes(false,true);
			if (is_array($Props)) foreach ($Props as $p){
				//Verification de la valeur
				if (!$this->Check($p,"","Conformity")){
					$error=0;
				}
			}
			//Verification des cardinalites.
			#TODO
			return $error;
		}

		//Fonction d ajout d erreur dans le tableau
		function AddError($err){
			$this->Error[] = $err;
		}
		function Error() {
			return $this->Error;
		}

		function getReferences($Id)
		{
			$Ref = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->getReferences($Id);
		}

		function removeRef($Id)
		{
			$Ref = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->removeRef($Id);
		}

		function addRef($objId,$refId,$refType,$refModule,$Type)
		{
			$Ref = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass ]->addRef($objId,$refId,$refType,$refModule,$Type);
		}

		function getChilds($Type){
			//Renvoie un tableau contenant les enfants de l'objet en cours
			$Query = $this->ObjectType.'/'.$this->Id.'/'.$Type;
			return  $this->executeQuery($Query);
		}


		function getParents($Type=""){
			//Renvoie un tableau contenant les parents de l'objet en cours
			if ($this->Id!=0){
				$Query = $Type.'/'.$this->ObjectType.'/'.$this->Id;
				$Parents = $this->executeQuery($Query);
				if (is_array($Parents))foreach ($Parents as $k=>$Par) {
					if (strlen($Par["Module"])) {
						$Temp = genericClass::createInstance($Par["Module"],$Par);
						$Parents[$k] = $Temp;
					}
				}
			}
			return  $Parents;
		}

		function isRootConnected($Class) {
			$Temp = $this->getParents($Class);
			if (is_array($Temp))foreach ($Temp as $T){
				if ($T["Id"]==""||$T["Id"]==0) {
					return true;
				}
			}
			return false;
		}

		function getCard($Class) {
			$Card = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->IdObjClass]->getCard($Class);
			return $Card;
		}

		function executeQuery($Query) {
			//Execute les requetes envoyÃ©es
			$Results = $GLOBALS['Systeme']->Modules[$this->Module]->callData($Query);
			return $Results;
		}

		function getTotalNb(){
			$Result = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$this->ObjClassNum]->countDb();
			return $Result;
		}

		function ifSetPost(){
			$Nom = $this->ObjectType."_".$this->Id;
			return (empty($GLOBALS["Systeme"]->PostVars[$Nom])) ? "Rien" : $GLOBALS["Systeme"]->PostVars[$Nom];

		}
		################Fonctions specifiques







		################Fonctions Debug
		function varToStr($var){
			switch (gettype($var)) {
				case "array":
					$text='<span class="DebugPanelTitre">Array ()</span> {';
					$Clef = array_keys($var);
					$i=0;
					foreach ($var as $Key) {
						$text .= '<div class="DebugPanel">';
						$text .= '['.$Clef[$i].'] => ';
						$text .= $this->varToStr($Key);
						$i++;
						$text .= "</div>";
					}
					$text.='}';
					break;
				case "object":
					$text='<span class="DebugPanelTitre">Object ()</span> {';
					$Clef = get_object_vars($var);
					foreach ($Clef as $Key=>$Value) {
						$text .= '<div class="DebugPanel">';
						$text .= "[".$Key."] => ";
						$text .= $this->varToStr($Value);
						$text .= "</div>";
					}
					$text.='}';
					break;
				default:
					//C une Chaine
					$text = "$var";
					break;
			}
			return $text;
		}

		function isTail() {
			if ($this->Get("Bd")&&$this->Get("Bg")) return ($this->Get("Bd")-$this->Get("Bg")>1)?false:true; else return false;
		}

		function Debug() {
			//Imprime un rapport sur l objet en cours
			//On ajoute la feuille de style Debug dans l entete
			//On Affiche cet objet
			//		echo "La->".$this->varToStr($this);
			echo '<div class="DebugPanel">'.$this->varToStr($this)."</div>";
		}

		//FONCTION SCHEMA
		function isProperty($p){
			//Il faut le fair epour chaque langue
			$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
			foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
				if ($Lang!=$DefaultLanguage)$Tab= $this->Proprietes($Pref,true);
				else $Tab= $this->Proprietes();
				foreach ($Tab as $P) {
					if ($P["Nom"]==$p) return true;
				}
			}
			return false;
		}
		//FONCTION SCHEMA
		function getProperty($p){
			//Il faut le fair epour chaque langue
			$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
			foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
				if ($Lang!=$DefaultLanguage)$Tab= $this->Proprietes($Pref);
				else $Tab= $this->Proprietes();
				foreach ($Tab as $P) {
					if ($P["Nom"]==$p) {
						return $P;
					}
				}
				//return $this->Proprietes($Pref);
			}
			return false;
		}
		function isChild($p){
			$Tab= $this->typesEnfant();
			foreach ($Tab as $P) {
				if ($P["Titre"]==$p) return true;
			}
			return false;
		}
		function isParent($p){
			$Tab= $this->typesParent();
			foreach ($Tab as $P) {
				if ($P["Titre"]==$p) return true;
			}
			return false;
		}

                function buildParamQuery($Q,$Parent)
                  {
                      $Qs = array();
                      if ( $Q[0]=="(" ) {
                          preg_match("#\((.*)\)#",$Q,$QList);
                      }else {
                          $Q = str_replace("[>!]",$Parent->Id,$Q);
                          $Q = str_replace("[!]",$this->Id,$Q);
                          $Qs[] = $Q;
                          return $Qs;
                      }
                  }



       /**
         * Renvoie les propriétés par catégories, ordonnées selon les types
         *
         * @return [(String,[(String,String)])]
         */function getOrderedProperties($ParQuery="",$L="") {
             $Ordered = array();
             $buildCat = array("line" => array(),
                               "normal" => array(),
                               "block" => array(),
                               "media" => array());
             foreach( $this->Proprietes($L) as $p ) {
                 $cat = "";
                 if (empty($p["Category"]) ) {
                     $cat = "Autres";
                 }else {
                     $cat = $p["Category"];
                 }
                 if ( empty($p["Valeur"] ) ) {
                     $type = "normal";
                 }else {
                     $type = $p["displayType"];
                 }
                 //On verifie que la propriété ne doivent pas être cachée
                 //via une conditionnelle
                 $display= true;
                 if ( is_array($this->Conditions) ) foreach($this->Conditions as $C)
                   {
                    if ( in_array($p["Nom"],$C["PropsName"]) ) {
                        $val = "";
                        if ( empty($C["About"]) ) {
                            $val = $this->getHtmlVar("Form_".$C["Name"] );
                            if ( !$val ) {
                                $val = $this->Get($C["Name"]);
                            }
                        }else {
                            $Parents = $this->getParents($C["About"] );
			    if (empty($Parents) && !$this->Id)
                              {
                                  $Parents = $this->doQuery($this->Module,$ParQuery);
                                  $Parents[0] = genericClass::createInstance($this->Module,$Parents[0] );
                                  
                              }
                            $val = $Parents[0]->Get($C["Name"] );
                        }
                        if ( !in_array($val,$C["Value"] ) ) {
                            $display = false;
                        }
                    }
                   }
                 
                 if ( !$p["hidden"] && !$p["auto"] && $display) {
                     if ( !array_key_exists($cat,$Ordered) ) {
                         $Ordered[$cat] = $buildCat;
                     }
                     $Ordered[$cat][$type][] = $p;
                 }
             }
             return $Ordered;
         }


       /**
         * Renvoie le type d'affichage pour un type donné
         *
         * @param String $Type Le type
         * @return String
         */function getDisplayType( $Type ) {
             $normalTypes = array("varchar","int","private",
                                  "password","alias","objectclass",
                                  "color","random","metat",
                                  "metad","id","autodico",
                                  "mail","url","private",
                                  "order","date","price",
                                  "pourcent","link","canonic",
                                  "langfile","string");
             $lineTypes = array("titre");
             $blockTypes = array("text","txt","html",
                                 "bbcode");
             $mediaTypes = array("file","image");
             if ( in_array($Type,$normalTypes) ) {
                 return "normal";
             }elseif ( in_array($Type,$lineTypes ) ) {
                 return "line";
             }elseif ( in_array($Type,$blockTypes) ) {
                 return "block";
             }elseif ( in_array($Type,$mediaTypes) ) {
                 return "media";
             }else {
                 return "normal";
             }
         }
}
